//
//  EeTopStyle.swift
//  ETNavBarTransparentDemo
//
//  Created by zhu xietong on 2017/9/28.
//  Copyright © 2017年 zhuxieong. All rights reserved.
//

import Foundation
import UIKit
import Eelay
import RTRootNavigationController


public extension UIViewController{
    
}

public protocol EeTopStyleSupport {
    var initTopStyle:EeTopStyle{get}
}

public enum EeBgStyle{
    case blur(UIBlurEffect.Style)
    case color(UIColor)
    case image(UIImage)
    case `default`
    case none
}

public enum EeShadowStyle{
    case color(UIColor)
    case image(UIImage)
    case none
}

public enum NavMode{
    case eenav
    case rtnav
    
    
    public static var rtnav_init:()->Void = {
        if let cls = NSClassFromString("soapp.RTNavigtion"){
            if let rtnav = cls as? NSObject.Type{
                let _ = rtnav.init()
            }
//            RTRootNavigationController._swizzle_rt_navigation()
        }
    }
    
    public enum Notice:String,NotifyType{
        case eenav_build = "eenav_build"
        case rtnav_build = "rtnav_build"
        
        public var name: Notification.Name{
            return "NavMode.Notice.\(self.rawValue)".notice_name
        }
    }
}




extension  UIViewController
{
   
    
}







public var RTRootNavigationControllerSubClass:RTRootNavigationController.Type? = nil

public func RootNavigationController(rootViewController:UIViewController)->UINavigationController{
    switch EeTopStyle.mode {
    case .eenav:
        return EeNavigationController(rootViewController: rootViewController)
    default:
        if let rtnav = RTRootNavigationControllerSubClass{
            return rtnav.init(rootViewController: rootViewController)
        }
        guard let cls = NSClassFromString("RTRootNavigationController") else {
            return UINavigationController(rootViewController: rootViewController)
        }
        guard let rtnav = cls as? UINavigationController.Type else {
            return UINavigationController(rootViewController: rootViewController)
        }
        return rtnav.init(rootViewController: rootViewController)
    }
}

func getNavBack(view:UIView) -> UIView? {
    _ = view.description

    if view.subviews.count < 1{
        return nil
    }
    
    if(view.description.contains("_UIBarBackground")){
        if (view.__extention["_bkV"] as? UIImageView) != nil{
            return view
        }
        
        if let v = view.subviews.first{
            
            if let imgV = v as? UIImageView{
//                print("---KKKK--",imgV)
                view.insertSubview(v, belowSubview: imgV)
                let aImgV = UIImageView()
                view.eelay = [
                    [aImgV,[ee.T.L.B.R]]
                ]
                
                aImgV.__extention["isOldNavBak"] = "YES"
                view.__extention["_bkV"] = aImgV
                return aImgV
            }
//            return v
        }
        return view
    }
    let sb = view.subviews
    
    for v in sb {
        if v.description.contains("UIBarBackgroundShadowView"){
            return v.superview
        }
        else if (v.description.contains("UIVisualEffectView")){
            return v
        }
        else{
            
            if v.subviews.count > 0{
                let r = getNavBack(view: v)
                if r != nil{
                    return r
                }
            }
            return getNavBack(view: v)
            
        }
    }
    
    return nil
}



var trantiImage = UIImage.image(.clear)
extension UINavigationBar{
    private struct __NavAssociatedKeys {
        static var _backgroundView_key = "_backgroundView_key"
    }
    
    public var _backgroundView: UIView? {
        get {
            if let obj = objc_getAssociatedObject(self, &__NavAssociatedKeys._backgroundView_key) as? UIView
            {
                return obj
            }
            let obj = getNavBack(view: self)
            if let v = obj{
                objc_setAssociatedObject(self, &__NavAssociatedKeys._backgroundView_key, v, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
            return obj
        }
        set {
            objc_setAssociatedObject(self, &__NavAssociatedKeys._backgroundView_key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
}

public struct EeTopStyle{
    
    public static var mode:NavMode = .rtnav{
        didSet{
           
            switch (mode){
            case .rtnav:
                UIViewController.open_top_swizzle()
                NavMode.rtnav_init()
            case .eenav:
                UIViewController.open_top_swizzle()
                EeNavigationController.open_nav_swizzle()
            }
        }
    }
    
    public init(){
    }
    
    var isValid:Bool = true
    

    
    public var backView:MoBackView?{
        get{
         
            if let v = self.controller?.eenavbar
            {
                return v
            }
            return nil
        }
    }
    
    
    
    var navAlphaView:UIView?{
        get{
            switch EeTopStyle.mode {
            case .rtnav:
//                let b = self.controller?.navigationController?.navigationBar.subviews.first?.subviews[1]
//                let b = controller?.navigationController?.navigationBar.subviews.first
                return controller?.navigationController?.navigationBar._backgroundView
            default:
                if let v = self.controller?.eenavbar
                {
                    return v
                }
            }
            
            return nil
        }
    }
    public weak var controller:UIViewController? = nil
    {
        didSet{

            self.isValid = true


            if let _ = controller as? RTContainerNavigationController{
                self.isValid = false
            }
            let strs = [
                "UIInput",
                "InputView",
                "UIAlertController",
                "UIApplicationRotationFollowingController",
                "PopupDialog",
                "RTContainerController",
                "RTContainerNavigationController",
                "UINavigationController",
                "RTContainerViewController"
            ]


            if "\(self)".contain(strings: strs){
                self.isValid = false
            }

            
          
            switch EeTopStyle.mode {
            case .rtnav:
                self.playUp()
            default:
                break
            }
            //            self.playUp()
        }
    }
    public var statusBarStyle:UIStatusBarStyle = .default
    {
        didSet{
            controller?.setNeedsStatusBarAppearanceUpdate()
        }
    }
    public var navTintColor: UIColor = UINavigationBar.appearance().tintColor ?? .white
    {
        didSet{
            if !isValid{
                return
            }

            controller?.navigationController?.navigationBar.tintColor = navTintColor
        }
    }
    

    private var __navBarBgAlpha:CGFloat = 1.0
    public var navBarBgAlpha:CGFloat
    {
        set{
            __navBarBgAlpha = newValue
            if __navBarBgAlpha > 1{
                __navBarBgAlpha = 1
            }
            if __navBarBgAlpha < 0{
                __navBarBgAlpha = 0
            }
            self.navAlphaView?.alpha = __navBarBgAlpha
        }
        get{
            return __navBarBgAlpha
        }
     
    }
    
    public var isTranslucent:Bool = true
    
    public var navBarBgStyle:EeBgStyle = .default
    {
        didSet{
            if !isValid{
                return
            }
            switch navBarBgStyle {
            case .color(let color):
                backView?.backgroundColor = color
            default:
                break
            }
//            self.backView?.style = self
        }
    }
    public var titleTextAttributes:[NSAttributedString.Key:Any] = [NSAttributedString.Key:Any]()
    {
        didSet{
            if !isValid{
                return
            }
            controller?.navigationController?.navigationBar.titleTextAttributes = titleTextAttributes
        }
    }
    
    public var navBarShadow:EeShadowStyle = .none{
        didSet{
            
            switch navBarShadow {
                 case .color(let color):
                     self.shadowImage = UIImage.image(color: color, frame: CGRect(x: 0, y: 0, width: 1, height: TP.separatorHeight))
                 case .image(let img):
                     self.shadowImage = img
                 default:
                     self.shadowImage = nil
                 }
        }
    }
    
    public var shadowImage:UIImage?{
        set{
            if !isValid{
                return
            }
            switch EeTopStyle.mode {
            case .rtnav:
                if let img = newValue{
                   controller?.navigationController?.navigationBar.shadowImage = img
               }else{
                   controller?.navigationController?.navigationBar.shadowImage = UIImage.image(.clear)
               }
            default:
                controller?.navigationController?.navigationBar.shadowImage = UIImage.image(.clear)
                if let img = newValue{
                    controller?.eenavbar.shadowImageV.style = EeShadowStyle.image(img)
                }
            }
        }
        get{
            return controller?.navigationController?.navigationBar.shadowImage
        }
    }
    
    
    public mutating func playUp()  {
        if !isValid{
            return
        }
        controller?.navigationController?.navigationBar.titleTextAttributes = self.titleTextAttributes
        controller?.setNeedsStatusBarAppearanceUpdate()
        
        switch navBarShadow {
        case .color(let color):
            
            self.shadowImage = UIImage.image(color: color, frame: CGRect(x: 0, y: 0, width: 1, height: TP.separatorHeight))
        case .image(let img):
            self.shadowImage = img
        default:
            self.shadowImage = nil
        }
        
        var isOldNav = false

        switch EeTopStyle.mode {
        case .eenav:
            break
        default:
            switch navBarBgStyle {
            case .color(let color):
                navController?.navigationBar.barTintColor = color
                navController?.navigationBar._backgroundView?.backgroundColor = color
//                navController?.navigationBar.setBackgroundImage(UIImage.image(color, size: [Swidth,TP.topHeight]), for: .default)
                let tag = navAlphaView?.__extention["isOldNavBak",""] ?? ""
                
                if tag == "YES"{//iOS12 下设置背景无效时采用该方式Alpha
//                    navAlphaView?.isHidden = true
                    navAlphaView?.superview?.backgroundColor = .clear
                    navController?.navigationBar.setBackgroundImage(trantiImage, for: .default)
                    navAlphaView?.backgroundColor = color
                    isOldNav = true
                }else{
                    navController?.navigationBar.setBackgroundImage(UIImage.image(color, size: [Swidth,TP.topHeight]), for: .default)

                }
                navController?.navigationBar.isTranslucent = self.isTranslucent



            case .image(let img):
                navController?.navigationBar.setBackgroundImage(img, for: .default)
            default:
                break
            }
        }
        
        navController?.navigationBar.tintColor = navTintColor
//        if !isOldNav{
            navAlphaView?.alpha = navBarBgAlpha
//        }
        
    }
    
    var navController:UINavigationController?{
        get{
            return self.controller?.navigationController
        }
    }
}




extension EeTopStyleSupport where Self:UIViewController{
    var initTopStyle:EeTopStyle{
        get{
            return EeTopStyle.default
        }
    }
}


extension UIViewController
{
    private static let __onceToken = UUID().uuidString
    public class func open_top_swizzle() {
        guard self == UIViewController.self else { return }
        DispatchQueue.once(token: __onceToken) {
            let needSwizzleSelectorArr = [(#selector(getter:UIViewController.preferredStatusBarStyle),#selector(getter:UIViewController.et_preferredStatusBarStyle))]
            for selector in needSwizzleSelectorArr {
                let originalMethod = class_getInstanceMethod(UIViewController.self, selector.0)
                let swizzledMethod = class_getInstanceMethod(UIViewController.self, selector.1)
                let didAddMethod: Bool = class_addMethod(self, selector.0, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
                if didAddMethod {
                    class_replaceMethod(self, selector.1, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
                } else {
                    method_exchangeImplementations(originalMethod!, swizzledMethod!)
                }
            }
        }
    }
    
//    @objc func et_viewWillAppear(_ animated: Bool) {
////        self.top_style.playUp()
//        et_viewWillAppear(animated)
//    }
//
    
    
    @objc open var et_preferredStatusBarStyle: UIStatusBarStyle {
        return self.top_style.statusBarStyle
    }
    
    fileprivate struct EeTopStyleKey {
        static var TopStyle: EeTopStyle = EeTopStyle()
    }
    
    
    public var top_style:EeTopStyle{
        get {
            guard let style = objc_getAssociatedObject(self, &EeTopStyleKey.TopStyle) as? EeTopStyle else {
                let sty = (self as? EeTopStyleSupport)?.initTopStyle ?? EeTopStyle.default
                var new_value = sty
                if !(self is UINavigationController){
                    objc_setAssociatedObject(self, &EeTopStyleKey.TopStyle, new_value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                    new_value.controller = self
                }
                return new_value
            }
            return style
        }
        
        
        set {
            if (self is UINavigationController){
                return
            }
            var new_value = newValue
            new_value.controller = self
//            new_value.playUp()
            objc_setAssociatedObject(self, &EeTopStyleKey.TopStyle, new_value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            
        }
    }
}


